package com.bub.pay.api.controller;


import com.bub.pay.core.entity.domain.SysPerm;
import com.bub.pay.core.entity.domain.SysRole;
import com.bub.pay.core.entity.domain.SysRolePerm;
import com.bub.pay.core.entity.dto.role.SysRoleDTO;
import com.bub.pay.core.entity.dto.system.UpSysPermDto;
import com.bub.pay.core.entity.vo.user.AddRoleVo;
import com.bub.pay.core.entity.vo.user.SysPermVo;
import com.bub.pay.core.entity.vo.user.SysRoleVo;
import com.bub.pay.core.entity.vo.user.UpdateRoleVo;
import com.bub.pay.core.enums.DeleteFlagEnum;
import com.bub.pay.core.manager.menu.PermManager;
import com.bub.pay.core.manager.role.RoleManager;
import com.bub.pay.core.manager.role.menu.RolePermManager;
import com.bub.pay.framework.common.base.Cause;
import com.bub.pay.framework.common.base.Module;
import com.bub.pay.framework.common.constant.SystemConstants;
import com.bub.pay.framework.common.entity.model.SessionModel;
import com.bub.pay.framework.common.exception.GlobalException;
import com.bub.pay.framework.common.util.CollectionUtil;
import com.bub.pay.framework.common.util.ContextHolder;
import com.bub.pay.framework.common.util.StrUtil;
import com.bub.pay.framework.wrap.annotation.SysLog;
import com.bub.pay.framework.wrap.annotation.SysLogType;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@SysLogType("角色管理")
@RestController
@RequestMapping("admin/role")
public class RoleController extends BaseController {

    private final Logger logger = LoggerFactory.getLogger(RoleController.class);

    @Resource
    private RoleManager roleManager;

    @Resource
    private RolePermManager rolePermManager;

    @Resource
    private PermManager permManager;

    @SysLog("分页查询角色列表")
    @PostMapping("listPage")
    @RequiresPermissions("employeeManage:rolePermission:view")
    public Object roleList(@RequestBody SysRoleVo roleVo) {
        SessionModel sessionModel = ContextHolder.currentUserInfo();
        PageHelper.startPage(roleVo.getPageNo(), roleVo.getPageSize());
        Example roleExample = new Example(SysRole.class);
        Example.Criteria roleCriteria = roleExample.createCriteria()
                .andEqualTo("extendId", sessionModel.getExtendId())
                .andEqualTo("type", SystemConstants.SYS_TYPE_ADMIN);
        if (StringUtils.isNotBlank(roleVo.getName())) {
            roleCriteria.andEqualTo("name", roleVo.getName());
        }
        if (StringUtils.isNotBlank(roleVo.getCreateTimeStart())) {
            Date minStringDate;
            try {
                minStringDate = DateUtils.parseDate(roleVo.getCreateTimeStart(), "yyyy-MM-dd HH:mm:ss");
            } catch (Exception e) {
                logger.error("总管理|角色创建时间起始日期筛选格式有误|请求参数|{}", roleVo.getCreateTimeStart());
                throw new GlobalException(Module.admin, Cause.params_fail);
            }
            roleCriteria.andGreaterThanOrEqualTo("createDate", minStringDate);
        }
        if (StringUtils.isNotBlank(roleVo.getCreateTimeEnd())) {
            Date maxStringDate;
            try {
                maxStringDate = DateUtils.parseDate(roleVo.getCreateTimeEnd(), "yyyy-MM-dd HH:mm:ss");
            } catch (Exception e) {
                logger.error("总管理|角色创建时间结束日期筛选格式有误|请求参数|{}", roleVo.getCreateTimeEnd());
                throw new GlobalException(Module.admin, Cause.params_fail);
            }

            roleCriteria.andLessThanOrEqualTo("createDate", maxStringDate);
        }
        if (StringUtils.isNotBlank(roleVo.getCode())) {
            roleCriteria.andEqualTo("code", roleVo.getCode());
        }
        roleCriteria.andEqualTo("delFlag", DeleteFlagEnum.using.flag);
        roleExample.orderBy("createDate").desc().orderBy("sortNum").desc();
        List<SysRole> listRole = roleManager.getByExample(roleExample);

        long total = 0;
        if (listRole instanceof Page) {
            total = ((Page) listRole).getTotal();
        }
        List<SysRoleDTO> sysRoleListDto = new ArrayList<>();
        if (!CollectionUtil.isNullOrEmpty(listRole)) {
            sysRoleListDto = listRole.stream().map(e -> {
                SysRoleDTO dto = new SysRoleDTO();
                BeanUtils.copyProperties(e, dto);
                Long roleId = dto.getId();
                if (!Objects.isNull(roleId)) {
                    dto.setPermSize(permManager.countPermSizeByRole(roleId));
                    dto.setEmployeeNum(permManager.countEmployeeNumByRole(roleId));
                }
                return dto;
            }).collect(Collectors.toList());
        }
        PageInfo pageInFo = new PageInfo<>(sysRoleListDto);
        pageInFo.setTotal(total);
        return pageInFo;
    }


    @SysLog("获取角色列表")
    @PostMapping("list")
    public Object roleList() {
        Example roleExample = new Example(SysRole.class);
        Example.Criteria criteria = roleExample.createCriteria();
        criteria.andEqualTo("type", SystemConstants.SYS_TYPE_ADMIN)
                .andEqualTo("delFlag", DeleteFlagEnum.using.flag);
        List<SysRole> listRole = roleManager.getByExample(roleExample);
        List<SysRoleDTO> sysRoleListDto = new ArrayList<>();
        if (!CollectionUtil.isNullOrEmpty(listRole)) {
            sysRoleListDto = listRole.stream().map(e -> {
                SysRoleDTO dto = new SysRoleDTO();
                BeanUtils.copyProperties(e, dto);
                Long roleId = dto.getId();
                if (!Objects.isNull(roleId)) {
                    dto.setPermSize(permManager.countPermSizeByRole(roleId));
                    dto.setEmployeeNum(permManager.countEmployeeNumByRole(roleId));
                }
                return dto;
            }).collect(Collectors.toList());
        }
        return sysRoleListDto;
    }

    @SysLog("添加角色")
    @PostMapping("addRole")
    @RequiresPermissions("employeeManage:rolePermission:add")
    public Object addRole(@RequestBody AddRoleVo addRoleVo) {
        logger.info("总管理|添加角色|请求参数|{}", addRoleVo);
        SessionModel sessionModel = ContextHolder.currentUserInfo();
        if (!StrUtil.checkParamByPattern("[\u4e00-\u9fa5a-zA-z0-9]{2,100}", addRoleVo.getName())) {
            logger.error("总管理|添加角色参数错误|请求参数|{}", addRoleVo);
            /*throw new GlobalException(Module.admin, Cause.admin_add_role_name_params_error);*/
        }
        SysRole roleName = new SysRole();
        roleName.setType(SystemConstants.SYS_TYPE_ADMIN);
        roleName.setName(addRoleVo.getName());
        roleName.setExtendId(sessionModel.getExtendId());
        if (roleManager.getCount(roleName) != 0) {
            logger.error("总管理|添加角色,角色名称重复|请求参数|{}", addRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_add_role_name_error);
        }
        SysRole roleCode = new SysRole();
        roleCode.setType(SystemConstants.SYS_TYPE_ADMIN);
        roleName.setExtendId(sessionModel.getExtendId());
        addRoleVo.setExtendId(sessionModel.getExtendId());
        addRoleVo.setType(SystemConstants.SYS_TYPE_ADMIN);
        if (StringUtils.isNotBlank(addRoleVo.getRemarks())) {
            addRoleVo.setRemarks(addRoleVo.getRemarks());
        }
        return roleManager.addRole(addRoleVo);
    }

    @SysLog("修改角色基本信息")
    @PostMapping("updateBaseRole")
    @RequiresPermissions("employeeManage:rolePermission:update")
    public Object updateBaseRole(@RequestBody UpdateRoleVo updateRoleVo) {
        logger.info("总管理|修改角色|请求参数|{}", updateRoleVo);
        SessionModel sessionModel = ContextHolder.currentUserInfo();
        if (Objects.isNull(updateRoleVo.getRoleId())) {
            logger.error("总管理|修改角色参数错误|请求参数|{}", updateRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_update_role_id_presence_error);
        }
        if (StringUtils.isNotBlank(updateRoleVo.getName())) {
            if (!StrUtil.checkParamByPattern("[\u4e00-\u9fa5a-zA-z0-9]{2,100}", updateRoleVo.getName())) {
                logger.error("总管理|修改角色参数错误|请求参数|{}", updateRoleVo);
                /*throw new GlobalException(Module.admin, Cause.admin_add_role_name_params_error);*/
            }
        }
        SysRole role = new SysRole();
        role.setId(updateRoleVo.getRoleId());
        role.setType(SystemConstants.SYS_TYPE_ADMIN);
        List<SysRole> sysRole = roleManager.getList(role);
        if (CollectionUtil.isNullOrEmpty(sysRole)) {
            logger.error("总管理|修改角色，角色Id不存在|请求参数|{}", updateRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_update_role_id_not_presence_error);
        }
        role = sysRole.get(0);
        //角色名称不能重复（查询同一类型，角色名称是否重复）
        if (StringUtils.isNotBlank(updateRoleVo.getName())) {
            SysRole roleEntity = new SysRole();
            roleEntity.setName(updateRoleVo.getName());
            roleEntity.setType(SystemConstants.SYS_TYPE_ADMIN);
            roleEntity.setExtendId(sessionModel.getExtendId());
            List<SysRole> roleList = roleManager.getList(roleEntity);
            if (!CollectionUtil.isNullOrEmpty(roleList)) {
                if (roleList.size() > 1 || !roleList.get(0).getId().equals( role.getId())) {
                    throw new GlobalException(Module.admin, Cause.admin_add_role_name_error);
                }
            }
        }
        updateRoleVo.setExtendId(sessionModel.getExtendId());
        return roleManager.updateRole(updateRoleVo);
    }

    @SysLog("修改角色权限")
    @PostMapping("updateRolePerm")
    @RequiresPermissions("employeeManage:rolePermission:bindAuth")
    public Object updateRolePerm(@RequestBody UpdateRoleVo updateRoleVo) {
        logger.info("总管理|修改角色|请求参数|{}", updateRoleVo);
        if (Objects.isNull(updateRoleVo.getRoleId())) {
            logger.error("总管理|修改角色,角色Id不存在|请求参数|{}", updateRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_update_role_id_presence_error);
        }
        SysRole role = new SysRole();
        role.setId(updateRoleVo.getRoleId());
        role.setType(SystemConstants.SYS_TYPE_ADMIN);
        if (roleManager.getCount(role) == 0) {
            logger.error("总管理|修改角色，ID指定角色不存在|请求参数|{}", updateRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_update_role_id_not_presence_error);
        }
        SessionModel sessionModel = ContextHolder.currentUserInfo();
        updateRoleVo.setExtendId(sessionModel.getExtendId());
        return permManager.updateRolePerm(updateRoleVo);
    }

    @SysLog("删除角色")
    @PostMapping("deleteRole")
    @RequiresPermissions("employeeManage:rolePermission:delete")
    public Object deleteRole(@RequestBody UpdateRoleVo deleteRoleVo) {
        if (Objects.isNull(deleteRoleVo.getRoleId())) {
            logger.error("总管理|删除角色参数错误|请求参数|{}", deleteRoleVo);
            throw new GlobalException(Module.admin, Cause.admin_delte_role_error);
        }
        SessionModel sessionModel = ContextHolder.currentUserInfo();
        deleteRoleVo.setExtendId(sessionModel.getExtendId());
        return roleManager.deleteRole(deleteRoleVo);
    }

    @SysLog("获取角色关联的用户")
    @PostMapping("queryUserByRole")
    public Object queryUserByRole(@RequestBody UpdateRoleVo queryVo) {
        if (Objects.isNull(queryVo.getRoleId())) {
            logger.error("总管理|删除角色参数错误|请求参数|{}", queryVo);
            throw new GlobalException(Module.admin, Cause.admin_delte_role_error);
        }
        SysRole role = roleManager.getById(queryVo.getRoleId());
        if (role == null) {
            logger.error("总管理|删除角色，角色不存在|请求参数|{}", queryVo);
            throw new GlobalException(Module.admin, Cause.admin_delte_role_not_presence_error);
        }
        return roleManager.queryUserByRole(queryVo);
    }

    /*@SysLog("同步商户权限")
    @PostMapping("syncMerchantPerm")
    @RequiresPermissions("employeeManage:authority:syncMerchantPerm")
    public Object syncMerchantPerm(@RequestBody RoleSyncVO syncVO) {
        Map<String, Object> resultMap = new HashMap<>();
        // 查询所有的商户权限
        Example roleExample = new Example(SysRole.class);
        roleExample.createCriteria().andEqualTo("type", UserTypeEnum.merchant.getType())
                .andEqualTo("isSys", 1)
                .andEqualTo("delFlag", DeleteFlagEnum.using.flag);
        List<SysRole> roleList = roleManager.getByExample(roleExample);

        // 商户权限列表
        Example permExample = new Example(SysPerm.class);
        permExample.createCriteria().andEqualTo("delFlag", DeleteFlagEnum.using.flag).andEqualTo("platformType", 1);
        List<SysPerm> permList = permManager.getByExample(permExample);
        Map<Long, SysPerm> permMap = permList.stream().collect(Collectors.toMap(BaseDomain::getId, sysPerm -> sysPerm));
        List<SysRolePerm> insertList = new ArrayList<>();
        List<SysRolePerm> deleteList = new ArrayList<>();
        logger.info("商户管理员条数,count:{}", roleList != null ? roleList.size() : "0");
        assert roleList != null;
        for (SysRole sysRole : roleList) {
            Example rolePerExample = new Example(SysRolePerm.class);
            rolePerExample.createCriteria().andEqualTo("delFlag", DeleteFlagEnum.using.flag).andEqualTo("roleId", sysRole.getId());
            List<SysRolePerm> sysRolePermList = rolePermManager.getByExample(rolePerExample);
            Map<Long, SysRolePerm> sysRolePermMap = Maps.newHashMapWithExpectedSize(sysRolePermList.size());
            sysRolePermList.forEach(sysRolePerm -> {
                sysRolePermMap.put(sysRolePerm.getPermId(), sysRolePerm);
                SysPerm sysPerm = permMap.get(sysRolePerm.getPermId());
                if (sysPerm == null) {
                    deleteList.add(sysRolePerm);
                }
            });
            permList.forEach(sysPerm -> {
                SysRolePerm sysRolePerm = sysRolePermMap.get(sysPerm.getId());
                if (sysPerm.getStatus() == 0) {
                    // 权限禁用
                    if (sysRolePerm != null) {
                        // 如果这个权限已经有 则删除
                        deleteList.add(sysRolePerm);
                    }
                } else {
                    // 权限启用
                    if (sysRolePerm == null) {
                        // 如果这个权限没有 则添加
                        sysRolePerm = new SysRolePerm();
                        sysRolePerm.setPermId(sysPerm.getId());
                        sysRolePerm.setRoleId(sysRole.getId());
                        insertList.add(sysRolePerm);
                        resultMap.put(sysPerm.getId().toString(), sysPerm.getName());
                    }
                }
            });
        }

        logger.info("需要增加的权限信息:|{}", JSON.toJSONString(insertList));
        logger.info("需要删除的权限信息:|{}", JSON.toJSONString(deleteList));

        if (syncVO.getOperatorType() == 1) {
            if (CollectionUtils.isNotEmpty(insertList)) {
                rolePermManager.insertList(insertList);
            }
            if (CollectionUtils.isNotEmpty(deleteList)) {
                deleteList.forEach(sysRolePerm -> {
                    sysRolePerm.setDelFlag(DeleteFlagEnum.using.flag);
                    rolePermManager.updateByPrimaryKeySelective(sysRolePerm);
                });
            }
        }

        return resultMap;
    }*/


    @SysLog("查询权限资源")
    @PostMapping("queryPerm")
    public Object queryMenus(@RequestBody SysPermVo permVo) {
        //查询出所有的权限，并且标注，当前角色所关联的权限
        SysRolePerm sysRolePerm = new SysRolePerm();
        sysRolePerm.setRoleId(permVo.getRoleId());
        List<SysRolePerm> listRolePerm = rolePermManager.getList(sysRolePerm);
        Map<String, String> permSelected = new HashMap<>();
        if (!CollectionUtil.isNullOrEmpty(listRolePerm)) {
            listRolePerm.forEach(e -> permSelected.put(e.getPermId().toString(), e.getPermId().toString()));
        }
        Example example = new Example(SysPerm.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("delFlag", DeleteFlagEnum.using.flag).andEqualTo("platformType", SystemConstants.SYS_TYPE_ADMIN);
        List<SysPerm> listPerm = permManager.getByExample(example);
        List<UpSysPermDto> listDto = new ArrayList<>();
        if (!CollectionUtil.isNullOrEmpty(listPerm)) {
            listDto = listPerm.stream().map(e -> {
                UpSysPermDto dto = new UpSysPermDto();
                BeanUtils.copyProperties(e, dto);
                if (StringUtils.isNotBlank(permSelected.get(dto.getId().toString()))) {
                    dto.setSelected(1);
                }
                return dto;
            }).collect(Collectors.toList());
        }
        return listDto;
    }

}
